package com.atguigu.juc.cf;

import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author yanglin
 * @create 2024-01-03 9:11 星期三
 * description:
 */
public class CompletableFutureMallDemo {

    static List<NetMall> list = Arrays.asList(
            new NetMall("jd"),
            new NetMall("dangdang"),
            new NetMall("taobao")
    );


    /**
     * 模拟单线程操作：获取各图书的价格
     */
    public static List<String> getPrice(List<NetMall> list,String productName){
        return list.stream()
                .map(netMall -> 
                        String.format(productName + " in %s price is %.2f",netMall.getNetMallName(),netMall.calcPrice(productName)))
                .collect(Collectors.toList());
    }


    /**
     * 性能提升
     * 使用CompletableFuture异步任务：获取各图书的价格
     */
    public static List<String> getPrice2(List<NetMall> list,String productName){
        return list.stream()
                .map(netMall -> 
                        CompletableFuture.supplyAsync(() -> 
                                String.format(productName + " in %s price is %.2f",netMall.getNetMallName(),netMall.calcPrice(productName))))
                .collect(Collectors.toList())
                .stream()
                .map(s -> s.join())
                .collect(Collectors.toList());
    }
    
    

    /**
     *  前置只是  join()与get()的区别
     */
    @Test
    public void testCompletableFutureMall() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            return "hello CompletableFutureMall";
        });

        //获取返回值
//        System.out.println(completableFuture.get());
        System.out.println(completableFuture.join());  //与get()作用一样，但是在编译时不检查异常
    }


    /**
     * 业务描述：
     *  1：需求
     *      1.1：同一款产品，同时搜索出同一款产品在各大电商平台的售价；
     *      1.2：同一款产品，同时搜索出本产品在同一个电商平台下，各入驻卖家的售价
     *      
     *  2：技术要求
     *      函数式编程
     *      链式编程
     *      Stream流式计算
     */
    @Test
    public void testCompletableFutureMall2(){
        
        //耗时：3024毫秒
        long st = System.currentTimeMillis();
        List<String> mysql = getPrice(list, "mysql");
        mysql.forEach(System.out::println);
        long et = System.currentTimeMillis();
        System.out.println("耗时：" + (et - st) + "毫秒");

        
        //耗时：1011毫秒
        long st2 = System.currentTimeMillis();
        List<String> mysql2 = getPrice2(list, "mysql");
        mysql2.forEach(System.out::println);
        long et2 = System.currentTimeMillis();
        System.out.println("耗时：" + (et2 - st2) + "毫秒");
    }

}

class NetMall {
    
    private String netMallName;

    public NetMall() {
    }

    public NetMall(String netMallName) {
        this.netMallName = netMallName;
    }

    public String getNetMallName() {
        return netMallName;
    }
    
    public double calcPrice(String productName){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
    
}
